import testTickets
import os
import sqlite3
import cPickle
from operator import itemgetter
from flask import Flask, render_template, request, redirect, jsonify
from func_lib.parse_excel import TestDrivenData, DataValidation, WriteBackResultToXls
from func_lib.run_test import RunTest
from func_lib.verify_xmlData import checkDiscoveryTree
from func_lib.make_result import DatabaseAction
from func_lib.helpers import log_progress
from genTicketsFile import gen_file
from commFunc import is_Windows
import time

ROOT_PATH = os.path.dirname(__file__)
TEST_MATERIAL_PATH = os.path.join(ROOT_PATH, 'testMaterial')
if not os.path.exists(TEST_MATERIAL_PATH):os.mkdir(TEST_MATERIAL_PATH)
TEST_RESULT_PATH = os.path.join(ROOT_PATH, 'testResult')
if not os.path.exists(TEST_RESULT_PATH):os.mkdir(TEST_RESULT_PATH)

app = Flask(__name__)

@app.route('/')
def home_page():

    return render_template('home.html')
#TODO----------------------------Helper Func----------------------------------------------------------------------------

def query_ticket_files_name_of_db(db_path):
    cur = sqlite3.connect(db_path)
    res = list(cur.execute('select case_name from records where case_action = 0'))
    cur.close()
    return res and [k[0] for k in res] or ["No Data, Maybe Result isn't complete"]

def query_db_without_g(db_path, tblName, query=None):
    cur = sqlite3.connect(db_path)
    res = list(cur.execute('select * from %s' % tblName))
    cur.close()
    return res

def parse_fin_data():
    fp = open(os.path.join(ROOT_PATH, 'testSchedule'), 'r')
    tmp = cPickle.load(fp)
    fp.close()
    scheduleDict = {}
    for i in tmp : scheduleDict[i[0].split(".")[0]] = []

    for k, v in app.config['finParams']:
        if '-' in k:
            scheduleDict[k.split('-')[0]].append(k.split('-')[1])
        else:
            scheduleDict[k.split('-')[0]].append((v,))
    for k, v in scheduleDict.items():
        tmp = []
        for i in v:
            if isinstance(i, tuple):
                tmp.append(v.pop(v.index(i))[0])
        tmp.append(v)
        scheduleDict[k] = tmp

    return scheduleDict

def check_connection(ip):

    if is_Windows():
        rev = os.system("ping -n 2 %s" % ip)
        return rev and "NO" or "YES"

    rev = os.system("ping -c 2 -t 2 %s" % ip)
    return rev and "NO" or "YES"


#TODO----------------------------Config Page----------------------------------------------------------------------------

@app.route('/makeConfig-1/', methods=['GET', 'POST'])
def makeConfig1():
    if request.method == "POST":
        formData = request.form.items()

        for i in formData:
            if i[0] == 'host_ip':
                app.config['host_ip'] = formData.pop(formData.index(i))
                break
        for i in formData:
            if i[0] == 'connType':
                app.config['connType'] = formData.pop(formData.index(i))
                break
        for i in formData:
            if i[0] == 'PassW':
                app.config['PassW'] = formData.pop(formData.index(i))
                break

        tmp = [(k, v) for k, v in formData]
        for i in range(0,len(tmp)):
            if tmp[i][0] == "PassW":
                del tmp[i]

        if tmp:
            with open(os.path.join(ROOT_PATH, 'testSchedule'), 'w') as fp:
                cPickle.dump(tmp, fp)
            return redirect('/makeConfig-15')
        else:
            pass
    app.config['dTree_flag'] = 0

    fileList = [fn for fn in os.listdir(TEST_MATERIAL_PATH) if fn.endswith('xls')]
    #ticketList = [tl for tl in os.listdir(os.path.join(TEST_MATERIAL_PATH, 'Tickets')) if not tl.startswith('.')]
    ticketList = [os.path.join(TEST_MATERIAL_PATH, 'Tickets'),]
    if fileList:
        return render_template('configPageOne.html', fl=fileList, tl=ticketList)
    else:
        return render_template('configPageOne.html', fl=['No files found'])


@app.route('/makeConfig-15', methods=['GET', 'POST'])
def makeConfig15():
    """
    verify the data from step 1
    """
    if check_connection(app.config['host_ip'][1]) == "NO":
        return render_template('configPageOneFive.html', noConn=True)

    fp = open(os.path.join(ROOT_PATH, 'testSchedule'), 'r')
    tmp = cPickle.load(fp)
    fp.close()

    exists_excel_path = []
    invalid_excel_path = []
    error_dict = {}

    for i in tmp:
        path = i[0].endswith('xls') and os.path.join(TEST_MATERIAL_PATH, i[0]) \
               or os.path.join(TEST_MATERIAL_PATH, i[0]+".xls")
        if os.path.exists(path):
            exists_excel_path.append(path)
        else:
            invalid_excel_path.append(path)


    for rPath in exists_excel_path:

        c = DataValidation(rPath)
        t = c.verify_data()
        if t:
            content = [(k, t[k]) for k in sorted(t)]
            error_dict[os.path.basename(rPath)] = content

    if not error_dict:
        return redirect('/makeConfig-2')
    else:
        return render_template('configPageOneFive.html', content=error_dict.items())

@app.route('/makeConfig-2', methods=['GET', 'POST'])
def makeConfig2():
    flag = [False]
    resDict = {}
    if request.method == 'POST':
        app.config['finParams'] = request.form.items()

        return redirect('/launchTest-1')

    fp = open(os.path.join(ROOT_PATH, 'testSchedule'), 'r')
    tmp = cPickle.load(fp)
    fp.close()
    fn = lambda x : os.path.exists(x) and x or "Invalid Path"
    for k, v in tmp:
        if v == 'on':flag[0]=True
        break

    treeList = lambda filePath : TestDrivenData(filePath).get_test_data(onlyTreeList=True)

    if flag[0]:
        for i, j in tmp:
            i = i.split('.')[0]
            tl = treeList(os.path.join(TEST_MATERIAL_PATH, i+".xls"))
            resDict[i] = (fn(os.path.join(TEST_MATERIAL_PATH, 'Tickets')), tl)
            #if "Fax" in i:resDict[i] = (fn(os.path.join(TEST_MATERIAL_PATH, 'Tickets', 'Fax Tickets')), tl)
            #if "Print" in i:resDict[i] = (fn(os.path.join(TEST_MATERIAL_PATH, 'Tickets', 'Print Tickets')), tl)
            #if "Scan" in i:resDict[i] = (fn(os.path.join(TEST_MATERIAL_PATH, 'Tickets', 'Scan Tickets')), tl)
        return render_template('configPageTwo.html', resList=resDict.items())
    else:
        for i, j in tmp:
            i = i.split('.')[0]
            tl = treeList(os.path.join(TEST_MATERIAL_PATH, i+".xls"))
            resDict[i] = (fn(os.path.join(TEST_MATERIAL_PATH, 'Tickets')), tl)
            #if "Fax" in i:resDict[i] = (fn(os.path.join(TEST_MATERIAL_PATH, 'Tickets', j)), tl)
            #if "Print" in i:resDict[i] = (fn(os.path.join(TEST_MATERIAL_PATH, 'Tickets', j)), tl)
            #if "Scan" in i:resDict[i] = (fn(os.path.join(TEST_MATERIAL_PATH, 'Tickets', j)), tl)
        return render_template('configPageTwo.html', resList=resDict.items())

#TODO----------------------------Launch Test----------------------------------------------------------------------------
@app.route('/launchTest-1', methods=['GET', 'POST'])
def launchTest1():
    if request.method == "POST":
        pass

    tmp = parse_fin_data()
    ip = app.config['host_ip'][1]
    ct = app.config['connType'][1]
    psw= app.config['PassW'][1].strip()

    dbWriter = DatabaseAction()
    tmpItems = tmp.items()

    caseCount = 0
    caseIndex = [1]

    if app.config.get('dTree_flag', 0):
        checkDiscoveryTree(dbWriter=dbWriter, host=ip)

    for i, j in tmpItems:
        caseCount += __get_case_count(os.path.join(TEST_MATERIAL_PATH, i+'.xls'), j[1])

    print "--- Total case count is %s ---" % caseCount
    for k, v in tmpItems:
        dbWriter.insert_data(k,0,0,0,0,0,0,0,0,0,0,0)
        if len(psw)!= 0:
            psw='admin:'+str(psw)
        r = RunTest(k+".xls", v[0], v[1], dbWriter, ct, s_flag=app.config['s_flag'], host_ip=ip,Psw=psw,
                    total_case_count=caseCount, caseIndex=caseIndex)
        r.run_loop()

    dbName = open(os.path.join(TEST_RESULT_PATH, '.dbName'), 'r').read()

    WriteBackResultToXls(dbName, tmp.keys()).write_back()

    return render_template('launchTestOne.html', dbName=dbName)

def __get_case_count(filePath, trees):
    """Base on selected parameters from parse_fin_data.
    calculate the total case count, so we can use this
    number to get current status after each test case finish
    """
    total_case_count = 0
    data = TestDrivenData(excelFilePath=filePath).get_test_data()
    for tree in trees:
        total_case_count += len(data[tree])
    return total_case_count


#TODO----------------------------Result Reviewer------------------------------------------------------------------------

@app.route('/resReview-1', methods=['GET', 'POST'])
def resReview1():
    if request.method == 'POST':
        resDB = request.form['selectedResult']
        dbPath = os.path.join(TEST_RESULT_PATH, resDB)
        app.config['resDBPath'] = dbPath
        return redirect('/resReview-2')
    dbName = open(os.path.join(TEST_RESULT_PATH, '.dbName'), 'r').read()
    dbName = dbName.split('.')[0]
    fileList = [fn for fn in os.listdir(TEST_RESULT_PATH) if fn.endswith('sqlite')]
    fileList.sort()

    fileListDetails = {}
    for fn in fileList:
        tmp = query_ticket_files_name_of_db(os.path.join(TEST_RESULT_PATH, fn))

        if tmp : fileListDetails[fn] = ", ".join(tmp)

    if fileList:
        return render_template('resReviewPageOne.html', fl=fileList, newRes = dbName, fld=fileListDetails)
    else:
        pass

@app.route('/resReview-2', methods=['GET', 'POST'])
def resReview2():
    """"""
    dTreeDetails = query_db_without_g(app.config['resDBPath'], 'discovery_tree')
    dTreeDetails_2 = query_db_without_g(app.config['resDBPath'], 'discovery_tree_2')

    resDetails = query_db_without_g(app.config['resDBPath'], 'records')

    printerDetails = query_db_without_g(app.config['resDBPath'], 'info')
    sorted_res = {}
    group_index = [resDetails.index(i) for i in resDetails if i[2] == "0"]
    if len(group_index) > 1:
        group_index = [(group_index[j], group_index[j+1]) for j in xrange(len(group_index)-1)]
        group_index.append((group_index[-1][1], len(resDetails)))
        for k, v in group_index:
            sorted_res[resDetails[k][1]] = resDetails[k+1:v]
    else:
        sorted_res[resDetails[0][1]] = resDetails[1:]

    for k, v in sorted_res.items():
        sorted_res[k] = sorted(v, key=itemgetter(-2))

    return render_template('resReviewPageTwo.html', resdb = "Result Details",
                            resD = sorted_res.items(), pd = printerDetails[0],
                            dTree=dTreeDetails, dTree2=dTreeDetails_2)

#TODO----------------------------Progress Function----------------------------------------------------------------------
@app.route('/_get_current_progress', methods=['GET'])
def _get_current_progress():
    from flask import jsonify
    print log_progress()
    return jsonify(res="123")


#TODO--------------------------------Ajax Function----------------------------------------------------------------------
@app.route('/_set_http_or_https')
def _set_http_or_https():
    app.config['s_flag'] = request.args.get('s_flag', 1, type=int)
    return "True"

@app.route('/_delete_selected_files')
def _delete_selected_files():
    for i in  request.args.getlist('selectedFiles[]'):
        try:
            os.remove(os.path.join(TEST_RESULT_PATH, i))
            os.remove(os.path.join(TEST_RESULT_PATH, i.split('.')[0]+'.xls'))
        except OSError:
            pass
    return ""

@app.route('/_set_check_dTree')
def _set_check_dTree():
    app.config['dTree_flag'] = request.args.get('dTree_flag', 0, type=int)
    print app.config['dTree_flag']
    return "True"

@app.route('/load_run_result', methods=['POST'])
def get_data():
    try:
        gen_file()
        time.sleep(3)
    except Exception as e:
        print "error:",e
    return jsonify({"run_status":"OK"})

if __name__ == '__main__':
    app.run(debug=True)